home *** CD-ROM | disk | FTP | other *** search
/ Reverse Code Engineering RCE CD +sandman 2000 / ReverseCodeEngineeringRceCdsandman2000.iso / RCE / Library / Manuels & Misc / Assembly / AOA.ZIP / CH02 / WLOGIC / EQNENTRY.PAS < prev    next >
Encoding:
Pascal/Delphi Source File  |  1995-12-30  |  24.1 KB  |  862 lines

  1. unit Eqnentry;
  2.  
  3. interface
  4.  
  5. uses WinTypes, WinProcs, Classes, Graphics, Forms, Controls, Buttons,
  6.   StdCtrls, ExtCtrls, Dialogs, SysUtils, LogicEV, Help1;
  7.  
  8. type
  9.   TEqnDlg = class(TForm)
  10.     OKBtn: TBitBtn;
  11.     CancelBtn: TBitBtn;
  12.     HelpBtn: TBitBtn;
  13.     Bevel1: TBevel;
  14.     InputEqn: TEdit;
  15.     procedure OKBtnClick(Sender: TObject);
  16.     procedure CancelBtnClick(Sender: TObject);
  17.     procedure InputEqnChange(Sender: TObject);
  18.     procedure HelpBtnClick(Sender: TObject);
  19.   private
  20.     { Private declarations }
  21.   public
  22.     { Public declarations }
  23.   end;
  24.  
  25. var
  26.  
  27.   LastEqn:string;
  28.   EqnDlg: TEqnDlg;
  29.  
  30.  
  31.  
  32.  
  33. procedure DrawTruths(var TTbl:TruthType);
  34.  
  35.  
  36. implementation
  37.  
  38.  
  39. var
  40.    thisTruth:TruthType;
  41.  
  42. {$R *.DFM}
  43.  
  44.  
  45.  
  46.  
  47. { RmvBlanks- Removes all spaces from a string.    }
  48.  
  49. procedure RmvBlanks(var Equation:string);
  50. var dest:integer;
  51.     i:integer;
  52.  
  53. begin
  54.  
  55.     dest := 1;
  56.     for i := 1 to length(Equation) do
  57.         if (Equation[i] <> ' ') then begin
  58.  
  59.             Equation[dest] := Equation[i];
  60.                 dest := dest + 1;
  61.  
  62.         end;
  63.  
  64. end;
  65.  
  66.  
  67.  
  68.  
  69. { DrawTruths- This procedure takes a truth table as a parameter and     }
  70. { draws that truth table on the CREATE page.  Zero variable functions    }
  71. { produce a blank truth table, one-variable functions produce a 1x2    }
  72. { truth table, two-variable functions produce a 2x2 table, three-    }
  73. { variable functions produce a 2x4 table, and four-variable functions    }
  74. { produce a 4x4 table.                            }
  75.  
  76. procedure DrawTruths(var TTbl:TruthType);
  77. var
  78.     i,j,
  79.     a,b,c,d,
  80.     Clk        :integer;
  81.  
  82.     { ToDigit converts the integer value at the given spot in the truth    }
  83.     { table to a '0' or '1' character and returns this character.    }
  84.  
  85.     function ToDigit(clk,d,c,b,a:integer):char;
  86.     begin
  87.  
  88.         result := chr(ord('0') + TTbl.tt[clk,d,c,b,a]);
  89.  
  90.     end;
  91.  
  92. begin {DrawTruth}
  93.  
  94.     {Initialize all the truth table labels to spaces.  We will fill    }
  95.         {in the necessary ones later.                    }
  96.  
  97.     with LogicEval do begin
  98.  
  99.             ba00.Caption := '';
  100.             ba01.Caption := '';
  101.             ba10.Caption := '';
  102.             ba11.Caption := '';
  103.  
  104.             dc00.Caption := '';
  105.             dc01.Caption := '';
  106.             dc10.Caption := '';
  107.             dc11.Caption := '';
  108.  
  109.             dc200.Caption := '';
  110.             dc201.Caption := '';
  111.             dc210.Caption := '';
  112.             dc211.Caption := '';
  113.  
  114.         end;
  115.  
  116.         { Clear all the labels in the truth table.  For functions with    }
  117.         { less than four variables, the unused squares need to be blank.}
  118.         { We will fill in the non-blank ones later.            }
  119.  
  120.         for clk := 0 to 1 do
  121.           for a:= 0 to 1 do
  122.             for b := 0 to 1 do
  123.               for c := 0 to 1 do
  124.                 for d := 0 to 1 do
  125.                 begin
  126.  
  127.                     tt[clk,d,c,b,a].Caption := '';
  128.  
  129.                 end;
  130.  
  131.         { Okay, fill in the truth tables and attach appropriate labels    }
  132.         { down here.  Since functions of different numbers of variables    }
  133.         { each produce completely different truth tables, the following    }
  134.         { case statement divides up the work depending on the number    }
  135.         { of variables in the function.                    }
  136.  
  137.     case TTbl.NumVars of
  138.  
  139.         { Handle functions of a single variable here.  Produce a 1x2    }
  140.         { truth table.                            }
  141.  
  142.         1:  begin
  143.  
  144.             for Clk := 0 to 1 do
  145.                   for a := 0 to 1 do
  146.                     tt[Clk,0,0,0,a].Caption := ToDigit(Clk,0,0,0,a);
  147.  
  148.                 with LogicEval do begin
  149.  
  150.                     ba00.Caption := ' ' + TTbl.theVars[0] + '''';
  151.                     ba01.Caption := ' ' + TTbl.theVars[0];
  152.  
  153.                 end;
  154.  
  155.             end;
  156.  
  157.         { Handle functions of two variables here, producing a 2x2    }
  158.         { truth table.  Note that this code swaps the B and C variables    }
  159.         { in the actual truth table to get a 2x2 format rather than a    }
  160.         { 1x4 format.                            }
  161.  
  162.         2:  begin
  163.  
  164.             for clk := 0 to 1 do
  165.                   for a:= 0 to 1 do
  166.                     for b:= 0 to 1 do
  167.                       tt[clk,0,b,0,a].Caption := ToDigit(clk,0,0,b,a);
  168.  
  169.                 with LogicEval do begin
  170.  
  171.                     ba00.Caption := ' ' + TTbl.theVars[0] + '''';
  172.                     ba01.Caption := ' ' + TTbl.theVars[0];
  173.  
  174.                     dc00.Caption := ' ' + TTbl.theVars[1] + '''';
  175.                     dc01.Caption := ' ' + TTbl.theVars[1];
  176.  
  177.                     dc200.Caption := ' ' + TTbl.theVars[1] + '''';
  178.                     dc201.Caption := ' ' + TTbl.theVars[1];
  179.  
  180.                 end;
  181.  
  182.             end;
  183.  
  184.  
  185.         { Process three-variable functions down here.  This code pro-    }
  186.         { duces a 2x4 truth table.                    }
  187.  
  188.         3:  begin
  189.  
  190.             for clk := 0 to 1 do
  191.                   for c := 0 to 1 do
  192.                     for b := 0 to 1 do
  193.                       for a := 0 to 1 do
  194.                       begin
  195.  
  196.                         tt[clk,0,c,b,a].Caption := ToDigit(clk,0,c,b,a);
  197.  
  198.                       end;
  199.  
  200.                 with LogicEval do begin
  201.  
  202.                     ba00.Caption := TTbl.theVars[1] + '''' +
  203.                                 TTbl.theVars[0] + '''';
  204.                     ba01.Caption := TTbl.theVars[1] + '''' +
  205.                                 TTbl.theVars[0];
  206.                     ba10.Caption := TTbl.theVars[1] +
  207.                                 TTbl.theVars[0] + '''';
  208.                     ba11.Caption := TTbl.theVars[1] +
  209.                                 TTbl.theVars[0];
  210.  
  211.                     dc00.Caption := ' ' + TTbl.theVars[2] + '''';
  212.                     dc01.Caption := ' ' + TTbl.theVars[2];
  213.  
  214.                     dc200.Caption := ' ' + TTbl.theVars[2] + '''';
  215.                     dc201.Caption := ' ' + TTbl.theVars[2];
  216.  
  217.                 end;
  218.  
  219.  
  220.             end;
  221.  
  222.  
  223.         { Produce a 4x4 truth table for functions of four variables.    }
  224.  
  225.         4:  begin
  226.  
  227.             for clk := 0 to 1 do
  228.                   for d := 0 to 1 do
  229.                     for c := 0 to 1 do
  230.                       for b := 0 to 1 do
  231.                           for a := 0 to 1 do
  232.                         begin
  233.  
  234.                             tt[clk,d,c,b,a].Caption :=
  235.                                         ToDigit(clk,d,c,b,a);
  236.  
  237.                         end;
  238.  
  239.                 with LogicEval do begin
  240.  
  241.                     ba00.Caption := TTbl.theVars[1] + '''' +
  242.                                 TTbl.theVars[0] + '''';
  243.                     ba01.Caption := TTbl.theVars[1] + '''' +
  244.                                 TTbl.theVars[0];
  245.                     ba10.Caption := TTbl.theVars[1] +
  246.                                 TTbl.theVars[0] + '''';
  247.                     ba11.Caption := TTbl.theVars[1] +
  248.                                 TTbl.theVars[0];
  249.  
  250.                     dc00.Caption := TTbl.theVars[3] + '''' +
  251.                                 TTbl.theVars[2] + '''';
  252.                     dc01.Caption := TTbl.theVars[3] + '''' +
  253.                                 TTbl.theVars[2];
  254.                     dc10.Caption := TTbl.theVars[3] +
  255.                                 TTbl.theVars[2] + '''';
  256.                     dc11.Caption := TTbl.theVars[3] +
  257.                                 TTbl.theVars[2];
  258.  
  259.                     dc200.Caption := TTbl.theVars[3] + '''' +
  260.                                 TTbl.theVars[2] + '''';
  261.                     dc201.Caption := TTbl.theVars[3] + '''' +
  262.                                 TTbl.theVars[2];
  263.                     dc210.Caption := TTbl.theVars[3] +
  264.                                 TTbl.theVars[2] + '''';
  265.                     dc211.Caption := TTbl.theVars[3] +
  266.                                 TTbl.theVars[2];
  267.  
  268.                 end;
  269.  
  270.  
  271.             end;
  272.  
  273.         end;
  274.  
  275. end;
  276.  
  277.  
  278.  
  279. { ParseEqn-    This function checks to see if an equation input by the    }
  280. {        user is syntactically correct.  If not, this function    }
  281. {        returns false.  If so, this function constructs the    }
  282. {        truth table for the equation by evaluating the function    }
  283. {        for all possible values of the clock, a, b, c, and d.    }
  284.  
  285. function ParseEqn:boolean;
  286. var
  287.     a,b,c,d,
  288.     clk,
  289.     i        :integer;
  290.     CurChar    :integer;
  291.     Equation    :string;
  292.     TruthVars    : set of char;
  293.  
  294.  
  295.     { Parse- Parses the "Equation" string and evaluates it.    }
  296.     { Returns true if expression is legal, returns        }
  297.     { false if the equation is syntactically incorrect.        }
  298.     {                                }
  299.     { Grammar:                            }
  300.     {        S -> X + S | X                    }
  301.     {        X -> YX | Y                    }
  302.     {        Y -> Y' | Z                    }
  303.     {        Z -> a .. z | # | ( S )                }
  304.  
  305.     function S:boolean;
  306.  
  307.         function X:boolean;
  308.         var dummy:boolean;
  309.  
  310.             function Y:boolean;
  311.  
  312.                     function Z:boolean;
  313.                         begin
  314.  
  315.                             case (Equation[CurChar]) of
  316.  
  317.                             { The following case handles parenthesized    }
  318.                             { expressions.                }
  319.  
  320.                             '(': begin
  321.  
  322.                                 inc(CurChar); { Skip the parenthesis.    }
  323.                                 Result := S;  { Check internal expr.    }
  324.  
  325.                                 { Be sure the expression ends with a    }
  326.                                 { closing parenthesis.            }
  327.  
  328.                                 if (Equation[CurChar] <> ')') then
  329.                                     Result := false
  330.                                 else    inc(CurChar);
  331.  
  332.                             end;
  333.  
  334.  
  335.                             { If this term is a variable name, we need    }
  336.                             { check a couple of things.  First of all,    }
  337.                             { equations cannot have more than four dif-    }
  338.                             { ferent variables.  The TruthVars set con-    }
  339.                             { tains the variables found in the equation    }
  340.                             { up to this point.  If the current vari-    }
  341.                             { able is not in this set, add it to the    }
  342.                             { set and bump the variable counter by one.    }
  343.                             { If the variable is already in the set,    }
  344.                             { then we've already counted it towards our    }
  345.                             { maximum of four variables.        }
  346.                             { We return true if we haven't exceeded our    }
  347.                             { four variable maximum.            }
  348.  
  349.                             'A'..'Z': begin
  350.  
  351.                                 if (not (Equation[CurChar] in TruthVars)) then
  352.                                 begin
  353.  
  354.                                     thisTruth.theVars[thisTruth.NumVars]:=
  355.                                     Equation[CurChar];
  356.                                     TruthVars := TruthVars +
  357.                                                 [Equation[CurChar]];
  358.                                     Result := thisTruth.NumVars < 4;
  359.                                     if Result then inc(thisTruth.NumVars);
  360.  
  361.                                 end
  362.                                 else Result := true;
  363.                                 inc(CurChar);
  364.  
  365.                             end;
  366.  
  367.  
  368.                             { The clock value ("#") and the zero and    }
  369.                             { one constants do not need any special    }
  370.                             { handling.  Just skip over them and return    }
  371.                             { true as the function result.        }
  372.  
  373.                             '#','0','1': begin
  374.  
  375.                                 Result := true;
  376.                                 Inc(CurChar);
  377.  
  378.                             end;
  379.  
  380.                             { If not one of the above symbols, we've    }
  381.                             { got an illegal symbol in the equation.    }
  382.                             { Return an error if this occurs.        }
  383.  
  384.                             else Result := false;
  385.  
  386.                             end;
  387.                         end;
  388.  
  389.                 { Y handles all sub-expressions of the form <var>'.    }
  390.  
  391.                 begin {Y}
  392.  
  393.                     { Note: This particular operation is left recursive    }
  394.                     { and would require considerable grammar transform-    }
  395.                     { ation to repair.  However, a simple trick is to    }
  396.                     { note that the result would have tail recursion    }
  397.                     { which we can solve iteratively rather than recur-    }
  398.                     { sively.  Hence the while loop in the following    }
  399.                     { code.                        }
  400.  
  401.                     Result := Z;
  402.                     while (Result) and (Equation[CurChar] = '''') do
  403.                         inc(CurChar);
  404.  
  405.                 end;
  406.  
  407.         { X handles all subexpressions containing concatenated values    }
  408.         { (i.e., logical AND operations).                }
  409.  
  410.         begin {X}
  411.  
  412.             Result := Y;
  413.         if Result and
  414.                    (Equation[CurChar] in ['A'..'Z','0','1','#','(']) then
  415.                     result := X;
  416.  
  417.         end;
  418.  
  419.  
  420.     { S handles all general expressions and, in particular, those tak-    }
  421.     { ing the form <var> + <var>.                    }
  422.  
  423.     begin {S}
  424.  
  425.         Result := X;
  426.         if Result and (Equation[CurChar] = '+') then
  427.         begin
  428.  
  429.             inc(CurChar);
  430.             Result := S;
  431.         end;
  432.  
  433.     end;
  434.  
  435.  
  436.  
  437.  
  438.     { These functions actually process an equation in order to    }
  439.     { generate the appropriate truth tables. The grammar is the    }
  440.     { same as the above, this code simply has sematic rules to    }
  441.     { actually compute results.                    }
  442.  
  443.     function E(a,b,c,d,clk:integer; Ach, Bch, Cch, Dch:char):integer;
  444.  
  445.         function F:integer;
  446.  
  447.             function G:integer;
  448.  
  449.                     function H:integer;
  450.                         var ch:char;
  451.                         begin
  452.  
  453.                             ch := Equation[CurChar];
  454.                                 case (ch) of
  455.  
  456.                         '(': begin
  457.  
  458.                                     inc(CurChar);
  459.                                         Result := E(a,b,c,d,clk,
  460.                                                 Ach, Bch, Cch, Dch);
  461.                                         inc(CurChar);
  462.  
  463.                                      end;
  464.  
  465.                                 'A'..'Z': begin
  466.  
  467.                                     if (ch = Ach) then
  468.                                            Result := a
  469.                                         else if (ch = Bch) then
  470.                                            Result := b
  471.                                         else if (ch = Cch) then
  472.                                            Result := c
  473.                                         else if (ch = Dch) then
  474.                                            Result := d;
  475.                                         inc(CurChar);
  476.  
  477.                                      end;
  478.  
  479.                                 '#':  begin
  480.  
  481.                                         Result := clk;
  482.                                     Inc(CurChar);
  483.  
  484.                                      end;
  485.  
  486.  
  487.                                 '0':  begin
  488.  
  489.                                         Result := 0;
  490.                                     Inc(CurChar);
  491.  
  492.                                      end;
  493.  
  494.  
  495.                                 '1': begin
  496.  
  497.                                         Result := 1;
  498.                                     Inc(CurChar);
  499.  
  500.                                      end;
  501.  
  502.                                 end;
  503.                         end;
  504.  
  505.                 begin {G}
  506.  
  507.                     Result := H;
  508.                     while (Equation[CurChar] = '''') do
  509.                     begin
  510.  
  511.                         inc(CurChar);
  512.                         Result := Result xor 1;
  513.  
  514.                     end;
  515.  
  516.                 end;
  517.  
  518.         begin {F}
  519.  
  520.  
  521.             Result := G;
  522.                 if (Equation[CurChar] in ['A'..'Z', '(', '#', '0','1']) then
  523.                     Result := Result and F;    {YX case}
  524.         end;
  525.  
  526.     begin {E}
  527.  
  528.         Result := F;
  529.         if (Equation[CurChar] = '+') then
  530.         begin
  531.  
  532.             inc(CurChar);
  533.             Result := Result or E(a,b,c,d,clk,
  534.                             Ach, Bch, Cch, Dch);
  535.         end;
  536.  
  537.     end;
  538.  
  539.  
  540.  
  541.  
  542.  
  543.     { Swap swaps characters in the "theVars" array.  ParseEqn uses this    }
  544.     { function when it sorts the "theVars" array.            }
  545.  
  546.     procedure swap(pos1,pos2:integer);
  547.     var
  548.         ch:char;
  549.     begin
  550.  
  551.         ch := thisTruth.theVars[pos1];
  552.         thisTruth.theVars[pos1] := thisTruth.theVars[pos2];
  553.         thisTruth.theVars[pos2] := ch;
  554.  
  555.     end;
  556.  
  557.  
  558. begin {ParseEqn}
  559.  
  560.     { Note that the input equation only contains uppercase characters    }
  561.     { at this point.  The code calling this function has seen to that.    }
  562.     { This statement appends a zero byte to the end of the string    }
  563.     { for use as a sentinel value.                    }
  564.  
  565.     Equation :=  EqnDlg.InputEqn.Text + chr(0);
  566.  
  567.     { Remove any spaces present in the string }
  568.  
  569.     RmvBlanks(Equation);
  570.  
  571.     { Some truth table initialization before we parse this equation:    }
  572.  
  573.     thisTruth.NumVars := 0;
  574.     TruthVars := [];
  575.  
  576.  
  577.     { At a minimum, the equation must have four characters: "F=A" plus    }
  578.     { a zero terminating byte.  If it has fewer than four characters,    }
  579.     { it cannot possibly be correct.                    }
  580.  
  581.     if (length(Equation) < 4) then
  582.     begin
  583.  
  584.         MessageDlg(
  585.             'Syntax error, functions take the form "<var> = <expr>".',
  586.             mtWarning, [mbok], 0);
  587.         result := false;
  588.         exit;
  589.  
  590.     end
  591.  
  592.     { Functions must take the form "<var> = <expr>".            }
  593.  
  594.     else if (Equation[2] <> '=') or not (Equation[1] in ['A'..'Z', '#']) then
  595.     begin
  596.  
  597.         MessageDlg(
  598.             'Syntax error, functions take the form "<var> = <expr>".',
  599.             mtWarning, [mbok], 0);
  600.         result := false;
  601.         exit;
  602.  
  603.     end
  604.  
  605.     { Variables A..D and "#" are read-only, no functions can redefine    }
  606.     { them.  Check that here.                        }
  607.  
  608.     else if (Equation[1] in ['A'..'D','#']) then
  609.     begin
  610.  
  611.         MessageDlg(
  612.             'A-D and # are read-only and may not appear to the left of "=".',
  613.             mtWarning, [mbok], 0);
  614.         result := false;
  615.         exit;
  616.  
  617.     end
  618.  
  619.     { Okay, now all that's left to check is the expression.        }
  620.  
  621.     else begin
  622.  
  623.         { Set up the variable array.  Fill the fifth element with the    }
  624.         { name of the function we are defining.                }
  625.  
  626.         for i := 0 to 3 do thisTruth.theVars[i] := chr(0);
  627.         thisTruth.theVars[4] := Equation[1];
  628.  
  629.         { Start just past the "<var>=" portion of the equation and    }
  630.         { check to see if this equation is syntactically correct.    }
  631.  
  632.         CurChar := 3;
  633.     Result := S;
  634.  
  635.         { If we've got too may variables, complain about that here.    }
  636.  
  637.         if (thisTruth.NumVars > 4) then
  638.         begin
  639.  
  640.            MessageDlg('Too many variables in equation (max=4).',
  641.                       mtWarning, [mbok], 0);
  642.            result := false;
  643.  
  644.         end
  645.  
  646.         { Be sure there's no junk at the end of the equation.  If we're    }
  647.         { currently pointing at the sentinel character (the zero byte)    }
  648.         { then we've processed the entire equation.  If not, then there    }
  649.         { is junk at the end of the equation and we need to complain    }
  650.         { about this.                            }
  651.  
  652.         else if (Equation[CurChar] <> chr(0))then
  653.         begin
  654.  
  655.            MessageDlg('Syntax Error', mtWarning, [mbok], 0);
  656.            result := false;
  657.  
  658.         end;
  659.  
  660.  
  661.         if not Result then exit;
  662.  
  663.  
  664.         { Sort the array of characters used in this truth table.  This    }
  665.         { is a simple unrolled bubble sort of four elements.        }
  666.  
  667.         with thisTruth do begin
  668.  
  669.             if (NumVars >= 2) then
  670.                 begin
  671.  
  672.                     if theVars[0] > theVars[1] then swap(0,1);
  673.  
  674.                     if (NumVars >= 3) then
  675.                     begin
  676.  
  677.                         if theVars[1] > theVars[2] then swap(1,2);
  678.                 if theVars[0] > theVars[1] then swap(0,1);
  679.  
  680.                         if (NumVars = 4) then
  681.                         begin
  682.  
  683.                         if theVars[2] > theVars[3] then swap(2,3);
  684.                             if theVars[1] > theVars[2] then swap(1,2);
  685.                             if theVars[0] > theVars[1] then swap(0,1);
  686.  
  687.                         end;
  688.                     end;
  689.                 end;
  690.  
  691.  
  692.  
  693.                 { Evaluate the function for all possible values of Clk,    }
  694.                 { A, B, C, and D.  Store the results away into the    }
  695.                 { truth tables.                        }
  696.  
  697.                 for Clk := 0 to 1 do
  698.                   for a := 0 to 1 do
  699.                     for b := 0 to 1 do
  700.                       for c := 0 to 1 do
  701.                         for d := 0 to 1 do
  702.                         begin
  703.  
  704.                           CurChar := 3;
  705.                           tt[Clk,d,c,b,a] := e(a,b,c,d,Clk,
  706.                                       theVars[0],
  707.                                                 theVars[1],
  708.                                                 theVars[2],
  709.                                                 theVars[3]);
  710.                         end;
  711.  
  712.  
  713.                 { After building the truth tables, draw them.        }
  714.  
  715.                 DrawTruths(thisTruth);
  716.  
  717.         end;
  718.  
  719.  
  720.     end;
  721.  
  722. end;
  723.  
  724.  
  725.  
  726.  
  727.  
  728.  
  729.  
  730.  
  731. { If the user presses the OKAY button, then we need to parse the func-    }
  732. { tion the user has entered and, if it's correct, build the truth table    }
  733. { for that function.                            }
  734.  
  735. procedure TEqnDlg.OKBtnClick(Sender: TObject);
  736. var
  737.    ii:  integer;
  738.    ch:    char;
  739. begin
  740.  
  741.     { Convert all the characters in the equation to upper case.        }
  742.  
  743.     InputEqn.Text := UpperCase(InputEqn.Text);
  744.  
  745.     { Get the name of the function we are defining.            }
  746.  
  747.     ch := InputEqn.Text[1];
  748.  
  749.  
  750.  
  751.     with LogicEval do begin
  752.  
  753.        { See if this function is syntactically correct.  If it is, then    }
  754.        { ParseEqn also constructs the truth table for the equation.    }
  755.  
  756.        if (not ParseEqn) then
  757.        begin
  758.  
  759.             messagebeep($ffff);
  760.             InputEqn.Color := clRed;
  761.  
  762.        end
  763.        else begin
  764.  
  765.       InputEqn.Color := clWhite;
  766.  
  767.           { EqnSet is the set of all function names we're defined up to    }
  768.           { this point.  If the current function name is in this set,    }
  769.           { then the user has just entered a name of a pre-existing    }
  770.           { function.  Ask the user if they want to replace the exist-    }
  771.           { ing function with the new one.                }
  772.  
  773.           if (ch in EqnSet) then
  774.           begin
  775.  
  776.               if MessageDlg('Okay to replace existing function?',
  777.                       mtWarning, [mbYes, mbNo], 0) = mrYes then
  778.               begin
  779.  
  780.                 { Search for the equation in the equation list.        }
  781.  
  782.                 ii := 0;
  783.                 while (EqnList.Items[ii][1] <> ch) do inc(ii);
  784.  
  785.                 { Replace the equation and its truth table.        }
  786.  
  787.                   EqnList.Items[ii] := InputEqn.Text;
  788.                   TruthTbls[thisTruth.theVars[4]] := thisTruth;
  789.  
  790.               end
  791.  
  792.               { If the user elected not to replace the function, set    }
  793.               { thisTruth to the original truth table so we will draw    }
  794.               { the correct truth table (the original one) when we exit.}
  795.  
  796.               else begin
  797.  
  798.                    thisTruth := TruthTbls[InputEqn.Text[1]];
  799.  
  800.               end;
  801.  
  802.           end
  803.  
  804.           { If this isn't a duplicate function definition, enter the    }
  805.           { new function into the system down here.            }
  806.  
  807.           else begin
  808.  
  809.               LastEqn := InputEqn.Text;
  810.               TruthTbls[ch] := thisTruth;
  811.               EqnSet := EqnSet + [ch];
  812.               EqnList.Items.add(LastEqn);
  813.  
  814.           end;
  815.  
  816.           { Draw the truth table and close the equation editor dialog box. }
  817.  
  818.           DrawTruths(thisTruth);
  819.           EqnDlg.Close;
  820.  
  821.        end;
  822.  
  823.     end;
  824.  
  825. end;
  826.  
  827.  
  828. { If the user presses the cancel button, close the equation editor    }
  829. { dialog box and restore the default equation to the last equation    }
  830. { entered in the editor (rather than the junk that is in there now).    }
  831.  
  832. procedure TEqnDlg.CancelBtnClick(Sender: TObject);
  833. begin
  834.  
  835.      InputEqn.Text := LastEqn;
  836.      Close;
  837.  
  838. end;
  839.  
  840.  
  841. { If there was a syntax error, the equation input box will have a red    }
  842. { background.  The moment the user changes the equation the following    }
  843. { code will restore a white background.                    }
  844.  
  845. procedure TEqnDlg.InputEqnChange(Sender: TObject);
  846. begin
  847.  
  848.      InputEqn.Color := clWhite;
  849.  
  850. end;
  851.  
  852.  
  853.  
  854. procedure TEqnDlg.HelpBtnClick(Sender: TObject);
  855. begin
  856.     HelpBox.Show;
  857. end;
  858.  
  859.  
  860.  
  861. end.
  862.